﻿using System.Linq.Expressions;

namespace Ma.Bussiness.MaperExtend;

public static class ExpressionMapper
{
    /// <summary>
    /// 字典缓存--hash分布
    /// </summary>
    public static Dictionary<string,object> _Dic=new Dictionary<string,object>();

    /// <summary>
    /// 字典缓存表达式树
    /// </summary>
    /// <typeparam name="Tin"></typeparam>
    /// <typeparam name="Tout"></typeparam>
    /// <param name="tin"></param>
    /// <returns></returns>
    public static Tout Maper<Tin,Tout>(Tin tin)
    {
        string _key= string.Format("funckey_{0}_{1}",typeof(Tin).Name,typeof(Tout).Name);
        if (!_Dic.ContainsKey(_key) )
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(Tin), "p");
            List<MemberBinding> bindings = new List<MemberBinding>();
            foreach(var item in typeof(Tin).GetProperties())
            {
                MemberExpression property=Expression.Property(parameterExpression, typeof(Tin).GetProperty(item.Name));   
                MemberBinding binding= Expression.Bind(item, property);
                bindings.Add(binding);
            }
            foreach (var item in typeof(Tout).GetFields()) {
             MemberExpression property =Expression.Field(parameterExpression,typeof(Tin).GetField(item.Name));
                MemberBinding binding=Expression.Bind(item, property);
                bindings.Add(binding);
            }
            MemberInitExpression memberExpression = Expression.MemberInit(Expression.New(typeof(Tout)), bindings.ToArray());
            Expression<Func<Tin, Tout>> lambda = Expression.Lambda<Func<Tin, Tout>>(memberExpression, new ParameterExpression[] { parameterExpression });
            Func<Tin,Tout> func =lambda.Compile();
            _Dic.Add(_key, func);
        }
        return ((Func<Tin, Tout>)_Dic[_key]).Invoke(tin);
    }
}
